package com.example.kaogong.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.kaogong.common.utils.RespBean;
import com.example.kaogong.sys.mapper.*;
import com.example.kaogong.sys.pojo.*;
import com.example.kaogong.sys.pojo.dto.PaperCheckDto;
import com.example.kaogong.sys.pojo.dto.QuestionScoreDto;
import com.example.kaogong.sys.pojo.dto.StudentPaperDto;
import com.example.kaogong.sys.pojo.dto.StudentPaperQuestionDto;
import com.example.kaogong.sys.pojo.vo.StudentPaperDetailVo;
import com.example.kaogong.sys.pojo.vo.StudentPaperInfoVo;
import com.example.kaogong.sys.pojo.vo.StudentPaperQuestionVo;
import com.example.kaogong.sys.service.IExamService;
import com.example.kaogong.sys.service.IStudentPaperService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 学生试卷 服务实现类
 * </p>
 *
 * @author    
 * @since 2022-03-31
 */
@Service
public class StudentPaperServiceImpl extends ServiceImpl<StudentPaperMapper, StudentPaper> implements IStudentPaperService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private StudentPaperMapper studentPaperMapper;

    @Autowired
    private IExamService examService;

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private OptionMapper optionMapper;

    @Autowired
    private TeacherMapper teacherMapper;

    /**
     * 当前学生考试试卷提交
     * @param studentPaperDto
     * @param name
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespBean paperSubmit(StudentPaperDto studentPaperDto, String name) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", name));
        if (user == null || user.getRoleId() != 3)
            return RespBean.error();
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("uid", user.getUid()));
        if (student == null)
            return RespBean.error();

        StudentPaper studentPaper = new StudentPaper();
        studentPaper.setPaperId(studentPaperDto.getPaperId());
        studentPaper.setExamTime(LocalDateTime.now());
        studentPaper.setSid(student.getSid());
        studentPaper.setStatus(false);

        int insertStudentPaper = studentPaperMapper.paperSubmit(studentPaper);
        if (insertStudentPaper < 1)
            return RespBean.error();

        boolean insertStudentPaperQuestion = this.insertStudentPaperQuestion(studentPaperDto, studentPaper.getStudentPaperId());
        if (!insertStudentPaperQuestion) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespBean.error();
        }
        return RespBean.success();
    }

    /**
     * 当前登录学生获取所有作答试卷的基本信息
     * @param name
     * @return
     */
    @Override
    public RespBean<List<StudentPaperInfoVo>> getStudentAllStudentPaper(String name) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", name));
        if (user == null || user.getRoleId() != 3)
            return RespBean.error();
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("uid", user.getUid()));
        if (student == null)
            return RespBean.error();
        List<StudentPaperInfoVo> studentPaperInfoVoList = studentPaperMapper.getStudentAllStudentPaper(student.getSid());
        return RespBean.success(studentPaperInfoVoList);
    }

    /**
     * 根据作答试卷编号获取试卷详细作答信息
     * @param id
     * @return
     */
    @Override
    public RespBean<StudentPaperDetailVo> getStudentPaperDetailInfo(Integer id) {
        StudentPaper studentPaper = studentPaperMapper.selectOne(new QueryWrapper<StudentPaper>().eq("student_paper_id", id));
        if (studentPaper != null) {
            return RespBean.error();
        }
        StudentPaperInfoVo studentPaperInfoVo = new StudentPaperInfoVo();
        studentPaperInfoVo.setStudentPaperId(studentPaper.getStudentPaperId());
        studentPaperInfoVo.setStatus(studentPaper.getStatus());
        studentPaperInfoVo.setExamTime(studentPaper.getExamTime());
        studentPaperInfoVo.setFullMark(studentPaper.getFullMark());
        studentPaperInfoVo.setTotal(studentPaper.getTotal());
        StudentPaperDetailVo studentPaperDetailVo = this.getStudentPaperDetailVo(studentPaper.getStudentPaperId(), studentPaper.getPaperId());
        studentPaperDetailVo.setStudentPaperInfo(studentPaperInfoVo);
        return RespBean.success(studentPaperDetailVo);
    }

    /**
     * 当前登录教师获取所命题试卷所有未批阅的试卷基本信息
     * @param name
     * @return
     */
    @Override
    public RespBean<List<StudentPaperInfoVo>> getAllUncheckedPaper(String name) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", name));
        if (user == null || user.getRoleId() != 2)
            return RespBean.error();
        Teacher teacher = teacherMapper.selectOne(new QueryWrapper<Teacher>().eq("uid", user.getUid()));
        if (teacher == null)
            return RespBean.error();

        List<StudentPaperInfoVo> studentPaperInfoVoPage = studentPaperMapper.getAllUncheckedPaper(teacher.getTeacherId());
        return RespBean.success(studentPaperInfoVoPage);
    }

    /**
     * 教师批阅学生试卷
     * @param paperCheckDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean studentPaperCheck(PaperCheckDto paperCheckDto) {
        int score = 0;
        Exam exam = new Exam();
        for (QuestionScoreDto questionScoreDto : paperCheckDto.getQuestionScoreDtoList()) {
            exam.setScore(questionScoreDto.getScore());
            score += questionScoreDto.getScore();
            examMapper.update(exam, new UpdateWrapper<Exam>().eq("question_id", questionScoreDto.getQuestionId()).eq("student_paper_id", paperCheckDto.getStudentPaperId()));
        }
        StudentPaper studentPaper = studentPaperMapper.selectOne(new QueryWrapper<StudentPaper>().eq("student_paper_id", paperCheckDto.getStudentPaperId()));
        studentPaper.setStatus(true);
        if (studentPaper.getTotal() != null)
            studentPaper.setTotal(studentPaper.getTotal() + score);
        else
            studentPaper.setTotal(score);

        int update = studentPaperMapper.update(studentPaper, new UpdateWrapper<StudentPaper>().eq("student_paper_id", paperCheckDto.getStudentPaperId()));
        if (update < 1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespBean.error();
        }
        return RespBean.success();
    }

    /**
     * 根据学生考试试卷编号和试卷编号获取考试试卷详细信息
     * @param studentPaperId
     * @param paperId
     * @return
     */
    private StudentPaperDetailVo getStudentPaperDetailVo(Integer studentPaperId, Integer paperId) {
        //单选题
        List<StudentPaperQuestionVo> singleChoice = studentPaperMapper.getStudentPaperQuestion(studentPaperId, 1);
        singleChoice.forEach(question -> {
            question.setOptionVoList(optionMapper.selectOptionVoListByQuestionId(question.getQuestionId()));
        });

        // 多选题
        List<StudentPaperQuestionVo> multipleChoice = studentPaperMapper.getStudentPaperQuestion(studentPaperId, 2);
        multipleChoice.forEach(question -> {
            question.setOptionVoList(optionMapper.selectOptionVoListByQuestionId(question.getQuestionId()));
        });

        //判断题
        List<StudentPaperQuestionVo> judgement = studentPaperMapper.getStudentPaperQuestion(studentPaperId, 3);

        //填空题
        List<StudentPaperQuestionVo> fillBlank = studentPaperMapper.getStudentPaperQuestion(studentPaperId, 4);

        //论述题
        List<StudentPaperQuestionVo> essay = studentPaperMapper.getStudentPaperQuestion(studentPaperId, 5);

        StudentPaperDetailVo studentPaperDetailVo = new StudentPaperDetailVo();
        studentPaperDetailVo.setEssay(essay);
        studentPaperDetailVo.setJudgment(judgement);
        studentPaperDetailVo.setFillBlank(fillBlank);
        studentPaperDetailVo.setMultipleChoice(multipleChoice);
        studentPaperDetailVo.setSingleChoice(singleChoice);
        return studentPaperDetailVo;
    }

    private boolean insertStudentPaperQuestion(StudentPaperDto studentPaperDto, Integer studentPaperId) {
        List<StudentPaperQuestionDto> questionResponse = studentPaperDto.getQuestionResponse();
        List<Exam> examList = new ArrayList<>();
        int fullMark = 0;
        int score = 0;

        // 批改
        for (StudentPaperQuestionDto response : questionResponse) {
            Question question = questionMapper.selectOne(new QueryWrapper<Question>().eq("question_id", response.getQuestionId()));
            fullMark += question.getScore();

            // 答题情况存入数据库
            Exam exam = new Exam();
            exam.setQuestionId(response.getQuestionId());
            exam.setStudentPaperId(studentPaperId);
            if (question.getQuestionType() == 5)
                ; // do nothing
            else if (response.getResponse().equals(question.getAnswer())) {
                score += question.getScore();
                exam.setScore(question.getScore());
            } else
                exam.setScore(0);

            exam.setResponse(response.getResponse());
            examList.add(exam);
        }
        boolean saveBatch = examService.saveBatch(examList);
        if (!saveBatch)
            return false;

        StudentPaper studentPaper = new StudentPaper();
        if (studentPaperDto.getPaperType() == 1)
            studentPaper.setStatus(true);
        studentPaper.setFullMark(fullMark);
        studentPaper.setTotal(score);
        int update = studentPaperMapper.update(studentPaper, new UpdateWrapper<StudentPaper>().eq("student_paper_id", studentPaperId));
        if (update < 1)
            return false;
        return true;
    }
}
